How to make a DXL Context alive and shareable ?

Hi,

I need to share a DXL context between a "primary" DXL Script (a dxl context) and a "secondary" cone launch by an eval_ from the "primary" one.

I can't use the evalTop_ technique since:

  • evalTop_ is launched when the caller script terminates
  • forward references are not resolved in the DOORS startup process

Of course, I'm aware about precaution in memory allocation management... (Thanks to this post : https://www.ibm.com/developerworks/community/forums/html/topic?id=77777777-0000-0000-0000-000014942467)

 

Regarding several posts (written by Mathias Mamsch) It seems possible to make a dxl context alive by using a trigger... but it is not clear enough to me (Mathias, you mentioned a tutorial on this topic) :

  • Does it means that the dxl code loaded by a persistent trigger is done in the top level (I assume not, and if it is the case I assume it is with the same restrictions that ones on the DXL code for the startup process i.e : no forward references)
  • In the case of a dynamic trigger launched from a GUI : Does it mean that the dxl callback is executed in the context of the script that launched the GUI loop ? (I assume yes)
    • in that case, If I give the address of a function of this context to an eval_ context and I execute this function in it:
      • which allocation table will be used (the one of the eval_context or the one of the "gui" one?), in other words, if I execute this function, in which context it will be done ?

Thanks for your feedback in advance, I hope that will avoid many many hours of tests to find out these DXL behaviors.

kind regards.


jaracic - Tue Sep 20 10:16:37 EDT 2016

Re: How to make a DXL Context alive and shareable ?
Mathias Mamsch - Wed Sep 21 04:17:17 EDT 2016

Ok, lets try to get this straight. 

1. If you want to use eval_ to launch a child DXL and you want to pass data from the parent DXL to the child, you will do so by passing the memory address of the objects using addr_ (use 64 bit variant for DOORS 9.6, 64). 

2. Passing functions from one DXL context to another is like walking on very thin ice. 

- First of all you cannot directly pass a function from the parent to the child (since there is no such thing as a function reference)

- You can pass a reference to a function to the child DXL context by using a variable, dereferencing it inside the eval_ through a callback. E.g. 

int a = 123; 

void func (int x) {
   print "A Global: " a "\n"
   print "A func: " x "\n\n"; 
}

// 32 bit eval variant
string sCode = "

int b = 145; 

int adFunc = addr_ " ((addr_ func) int) "

void func_proxy(int par, void callback(int)) {
    callback(par); 
}

void func(int par) {
    func_proxy(par, addr_ adFunc);
}


func(b); 
"

print "Calling Func from parent: " 
func(a); 

print "Calling Func from eval: "

eval_ sCode

The above code however shows the problem. The eval_ code will NOT be executed in the parent context, but in its own context. The global variable referenced from "func" is translated by the DXL Processor to something like "the first variable on the stack" (relative stack reference). Since the parent DXL context and the child DXL context have different stacks, in the child the variable b will be used instead of a ... 

So to sum that up: You should never call a function inside another DXL context, because any global variable reference will go to Nirvana. 

What you should do instead: 

Put the function you need to call inside an include file, and include it from the eval_, e.g. the above example: 

// myinclude.inc
int a = 123; 

void func (int x) {
   print "A Global: " a "\n"
   print "A func: " x "\n\n"; 
}


// parent.dxl 
#include <myinclude.inc>
func(a); 

// child code: 
string sCode = "
#include <myinclude.inc> 

int b = 123; 
func(b); 
"

eval_ sCode

This way, each DXL context will have their own global variables in the correct places. Alright now lets get to the "keeping the DXL context alive". Keeping a DXL context alive has nothing to do with the above situation. Calling a child dxl from a parent using eval_ is very straight forward. The standard use case for keeping a DXL context alive is to share data from a global DXL with a DXL Layout Column. Here you should really rethink your options: 

- Can the data be shared in a native way (through a file or through an attribute value)? 

- Can you replace the DXL Layout attribute by a DXL attribute? 

If you really need data shared between two different DXL contexts, then you need to:

a) be able to pass at least one memory address from one DXL context to the other. 

b) Make sure the other DXL context stays alive (trigger or GUI)

Regarding a) you need to decide depending on your program which mechanism you will use. Regarding b) I would propose a GUI to keep the other DXL context alive. I posted a working example for a GUI backed layout column on the forum: 

https://www.ibm.com/developerworks/community/forums/html/topic?id=77777777-0000-0000-0000-000014890784#77777777-0000-0000-0000-000014891453

 

One more word regarding forward references: You say forward references are not resolved correctly on DOORS startup - you can replace forward references always by function references (as shown in the above example). But be aware of passing a function reference from a non global context to the global context (same reason as above). 

Maybe this helps, Regards, Mathias

 

 

Re: How to make a DXL Context alive and shareable ?
pommCannelle - Wed Sep 21 08:22:34 EDT 2016

(Real questioning , no troll : am I the only one to dump the data to be processed in a text file rather than a DOORS's variable, to perform treatments with the appropriate technology that does not suffer from memory leaks , allowing to build the GUI without effort, which has no problem of context etc ... and then  return to the doors's environment using a common 'file reading' way ? If not, I'll be happy to share with an experienced user of this forum)

Re: How to make a DXL Context alive and shareable ?
Mathias Mamsch - Wed Sep 21 10:02:52 EDT 2016

pommCannelle - Wed Sep 21 08:22:34 EDT 2016

(Real questioning , no troll : am I the only one to dump the data to be processed in a text file rather than a DOORS's variable, to perform treatments with the appropriate technology that does not suffer from memory leaks , allowing to build the GUI without effort, which has no problem of context etc ... and then  return to the doors's environment using a common 'file reading' way ? If not, I'll be happy to share with an experienced user of this forum)

No you are not ;-)  But it seems the old saying  "once you got a hammer, everything starts looking like a nail" applies also to DXL. And DXL is a very weirdly shaped, but expensive hammer, so you want to use it for everything! 

Re: How to make a DXL Context alive and shareable ?
jaracic - Thu Sep 22 08:01:25 EDT 2016

Mathias Mamsch - Wed Sep 21 04:17:17 EDT 2016

Ok, lets try to get this straight. 

1. If you want to use eval_ to launch a child DXL and you want to pass data from the parent DXL to the child, you will do so by passing the memory address of the objects using addr_ (use 64 bit variant for DOORS 9.6, 64). 

2. Passing functions from one DXL context to another is like walking on very thin ice. 

- First of all you cannot directly pass a function from the parent to the child (since there is no such thing as a function reference)

- You can pass a reference to a function to the child DXL context by using a variable, dereferencing it inside the eval_ through a callback. E.g. 

int a = 123; 

void func (int x) {
   print "A Global: " a "\n"
   print "A func: " x "\n\n"; 
}

// 32 bit eval variant
string sCode = "

int b = 145; 

int adFunc = addr_ " ((addr_ func) int) "

void func_proxy(int par, void callback(int)) {
    callback(par); 
}

void func(int par) {
    func_proxy(par, addr_ adFunc);
}


func(b); 
"

print "Calling Func from parent: " 
func(a); 

print "Calling Func from eval: "

eval_ sCode

The above code however shows the problem. The eval_ code will NOT be executed in the parent context, but in its own context. The global variable referenced from "func" is translated by the DXL Processor to something like "the first variable on the stack" (relative stack reference). Since the parent DXL context and the child DXL context have different stacks, in the child the variable b will be used instead of a ... 

So to sum that up: You should never call a function inside another DXL context, because any global variable reference will go to Nirvana. 

What you should do instead: 

Put the function you need to call inside an include file, and include it from the eval_, e.g. the above example: 

// myinclude.inc
int a = 123; 

void func (int x) {
   print "A Global: " a "\n"
   print "A func: " x "\n\n"; 
}


// parent.dxl 
#include <myinclude.inc>
func(a); 

// child code: 
string sCode = "
#include <myinclude.inc> 

int b = 123; 
func(b); 
"

eval_ sCode

This way, each DXL context will have their own global variables in the correct places. Alright now lets get to the "keeping the DXL context alive". Keeping a DXL context alive has nothing to do with the above situation. Calling a child dxl from a parent using eval_ is very straight forward. The standard use case for keeping a DXL context alive is to share data from a global DXL with a DXL Layout Column. Here you should really rethink your options: 

- Can the data be shared in a native way (through a file or through an attribute value)? 

- Can you replace the DXL Layout attribute by a DXL attribute? 

If you really need data shared between two different DXL contexts, then you need to:

a) be able to pass at least one memory address from one DXL context to the other. 

b) Make sure the other DXL context stays alive (trigger or GUI)

Regarding a) you need to decide depending on your program which mechanism you will use. Regarding b) I would propose a GUI to keep the other DXL context alive. I posted a working example for a GUI backed layout column on the forum: 

https://www.ibm.com/developerworks/community/forums/html/topic?id=77777777-0000-0000-0000-000014890784#77777777-0000-0000-0000-000014891453

 

One more word regarding forward references: You say forward references are not resolved correctly on DOORS startup - you can replace forward references always by function references (as shown in the above example). But be aware of passing a function reference from a non global context to the global context (same reason as above). 

Maybe this helps, Regards, Mathias

 

 

Thank you Mathias !!

Very valuable answer... as usual.